<!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Pokémon Go - Login</title>
        <link href="./bootstrap.min.css" rel="stylesheet">
    </head>
    <body style="overflow-x:hidden">
        <div class="row text-center">
            <div class="col-xs-12">
                <h1>Login to Pokémon GO</h1>
                <small id="version"></small>
                <br>
                <span id="update-notice" style="display:none;">
                    <a href="#" onclick="startUpdate()" style="color: #f00">
                        Update available, click here to install
                    </a>
                </span>
<!--                 <span>
                    <h4>
                        Follow <a href="https://twitter.com/icer5k" class="new-window">@icer5k</a> for updates.
                    </h4>
                </span> -->
                <br>
                <div class="row">
                    <div class="col-xs-3 col-xs-offset-3">
                        <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_donations&amp;business=KX3A74AJLWDKC&amp;lc=US&amp;item_name=Pokemon%20GO%20Desktop%20Map%20Donation&amp;item_number=POGO&amp;currency_code=USD&amp;bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted" class="new-window"><img src="./btn_donateCC_LG.gif" alt="PayPal - The safer, easier way to pay online!"></a>
                    </div>
                    <div class="col-xs-3">
                        <a href="#" data-toggle="modal" data-target="#btc-donate"><img src="./donation_btc.png"></a>

                    </div>
                </div>

                <hr>

                <div class="row">
                  <div class="col-xs-8 col-xs-offset-2">

                  <table class="table">
                      <thead>
                          <th>Service</th>
                          <th>Username</th>
                          <th></th>
                      </thead>
                      <tbody align="left" id="actDisplay">
                      </tbody>
                  </table>

                    <button class="btn btn-lg btn-block btn-primary"
                        data-toggle="modal" data-target="#add-acct">Add New Account</button>
                    <br>
                    <br>
                    <button class="btn btn-lg btn-block btn-success" onclick="startServer()">Start Server</button>

                  </div>
                </div>

                <hr>

                <h4>Google Maps Key</h4>
                <div class="row">
                    <div class="col-xs-8 col-xs-offset-2">
                        <input id="maps_api_key" class="form-control" type="text"
                            placeholder="Google Maps API Key" required>
                        <br>
                        <span style="color: #f00">
                            <a href="https://github.com/mchristopher/PokemonGo-DesktopMap/wiki/Google-Maps-API:-a-brief-guide-to-your-own-key" class="new-window">Follow this guide to generate your API key</a>
                        </span>
                    </div>
                </div>

                <hr>

                <h4>Config Options</h4>
                <div class="row">
                    <div class="col-xs-8 col-xs-offset-2">
                        <div class="row">
                            <div class="col-xs-12">
                                <div class="col-xs-6">
                                    <input id="lat" class="form-control"
                                        type="text" placeholder="Latitude">
                                </div>
                                <div class="col-xs-6">
                                    <input id="lon" class="form-control"
                                        type="text" placeholder="Longitude">
                                </div>
                            </div>
                        </div>
                            <div class="row">
                                &nbsp;
                            </div>
                            <div class="row">
                                <div class="col-xs-10 col-xs-offset-2">
                                    <div class="col-xs-8">
                                        <input id="address" class="form-control"
                                            type="text" placeholder="Address" onblur="toggleGeolocate()" onkeyup="toggleGeolocate()">
                                    </div>
                                    <div class="col-xs-2">
                                        <button id="address-locate" type="button" class="btn btn-primary" onclick="doGeolocate()" disabled="disabled">Locate</button>
                                    </div>
                                </div>
                            </div>
                            <div class="row">
                                &nbsp;
                            </div>
                        <div class="row">
                            <span>
                                Set to override, leave blank to use Geolocation
                            </span>
                        </div>
                    </div>
                </div>

                <hr>

                <h4>Scanning Options</h4>
                <div class="row">
                    <div class="col-xs-8 col-xs-offset-2">
                        <div class="row">
                            <div class="col-xs-6 col-xs-offset-3">
                                <div class="col-xs-10 col-xs-offset-1">
                                    <input id="radius" class="form-control"
                                        type="number" placeholder="Radius (default 7)">
                                </div>
                            </div>
                        </div>
                        <br>
                        <div class="row">
                            <span>
                                Larger numbers increase search area but updates are slower.
                            </span>
                        </div>
                    </div>
                </div>

                <hr>

                <h4>Server Options</h4>
                <div class="row">
                    <div class="col-xs-8 col-xs-offset-2">
                        <div class="row">
                            <div class="col-xs-12">
                                <div class="col-xs-8 col-xs-offset-2">
                                    <div class="checkbox">
                                        <label>
                                            <input type="checkbox" id="is_public">
                                            Server Mode / Allow access from anywhere
                                        </label>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>

                <br>
                <br>

            </div>
        </div>

        <div class="modal fade" id="btc-donate" tabindex="-1"
            role="dialog" aria-labelledby="mobileModalLbl">
          <div class="modal-dialog" role="document">
            <div class="modal-content">
              <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
                <h4 class="modal-title" id="mobileModalLbl">Bitcoin Donation</h4>
              </div>
              <div class="modal-body">
                <div class="text-center">
                    <div>
                        <h4>Send your donation to the following address:</h4>
                        <br>
                        <div id="btc-qrcode" align="center"></div>
                        <br>
                        <br>
                        <strong><a href="bitcoin:12WzBdaHox7mDcj2ScZnSwhXPSvcbwT8FK" class="new-window">12WzBdaHox7mDcj2ScZnSwhXPSvcbwT8FK</a></strong>
                    </div>
                </div>
              </div>
              <div class="modal-footer">
                <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
              </div>
            </div>
          </div>
        </div>

        <div class="modal fade" id="add-acct" tabindex="-1"
            role="dialog" aria-labelledby="actModalLbl">
          <div class="modal-dialog" role="document">
            <div class="modal-content">
              <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
                <h4 class="modal-title" id="actModalLbl">Add Account</h4>
              </div>
              <div class="modal-body">
                <div class="text-center">
                    <div>

                        <form id="act_form" onsubmit="verifyAndAddAccount()">
                          <input id="username" class="form-control" type="text" placeholder="Username" required>
                          <input id="password" class="form-control" type="password" placeholder="Password" required>
                          <div class="radio">
                            <label class="radio-inline"><input type="radio" name="acttype" value="ptc" checked>PTC</label>
                            <label class="radio-inline"><input type="radio" name="acttype" value="google">Google</label>
                        </div>
                          <button class="btn btn-lg btn-block btn-primary login" onclick="verifyAndAddAccount()">Add Account</button>
                        </form>

                        <br><br>

                        <span id="ptc_errors" style="color: #f00"></span>
                        <br>
                        <span style="color: #f00">
                            <a href="https://sso.pokemon.com/sso/login"
                                class="new-window">Create a PTC Account</a>
                        </span>

                    </div>
                </div>
              </div>
            </div>
          </div>
        </div>

    </body>

  <script type="text/javascript">
    window.$ = window.jQuery = require('./jquery.js');
  </script>
  <script src="./bootstrap.js"></script>
  <script src="./qrcode.js"></script>
  <script type="text/javascript">

    var fs = require('fs');
    var url = require('url');
    var request = require('request');
    var querystring = require('querystring');
    var electron = require('electron').remote;
    var BrowserWindow = electron.BrowserWindow;
    var ipcRenderer = require('electron').ipcRenderer;
    var open = require("open");

    var ptcJar = request.jar();
    var ptcReq = request.defaults({
        headers: {'User-Agent': 'niantic'},
        jar: ptcJar
    });

    var geoLat = 34.0432108;
    var geoLon = -118.2675059;
    var userAccounts = [];

    $( document ).ready(function(){
        // Show version
        $('#version').html('Version ' + electron.app.getVersion());
        $('.new-window').click(function(){
            open($(this).attr("href"));
            return false;
        });

        // Setup bitcoin QR
        new QRCode(
            document.getElementById("btc-qrcode"), {
                text: '12WzBdaHox7mDcj2ScZnSwhXPSvcbwT8FK',
                width: 128,
                height: 128
            });

        // Get checkbox state
        [
            'is_public'
        ].forEach(function(elem){
            if (localStorage.getItem(elem)) {
                document.getElementById(elem).checked = (
                    localStorage.getItem(elem) == "true");
            }
            $('#' + elem).change(function() {
                localStorage.setItem(elem, !!this.checked);
            });
        });

        setupValueAndSetter('radius', $('#radius'));

        setupValueAndSetter('last_lat', $('#lat'));
        setupValueAndSetter('last_lon', $('#lon'));
        setupValueAndSetter('maps_api_key', $('#maps_api_key'));

        if (localStorage.getItem('user_acct')) {
            userAccounts = JSON.parse(localStorage.getItem('user_acct'));
        }

        populateUserAccounts();
    });

    function setupValue(key, elem) {
        if (localStorage.getItem(key)) {
            elem.val(localStorage.getItem(key));
        }
    }

    function setupValueAndSetter(key, elem) {
        setupValue(key, elem);
        elem.change(function() {
            localStorage.setItem(key, elem.val());
        });
    }

    function checked(elemId) {
        return document.getElementById(elemId).checked;
    }

    function saveState() {
        localStorage.setItem('user_acct', JSON.stringify(userAccounts));
    }

    function populateUserAccounts() {
        var displayHtml = '';
        userAccounts.forEach(function(val, idx) {
            displayHtml += '<tr><td>'+val.type+'</td>';
            displayHtml += '<td>'+val.user+'</td>';
            displayHtml += '<td><a href="#" onclick="deleteUser('+idx+')">[X]</a></td></tr>';
        });
        $('#actDisplay').html(displayHtml);
        saveState();
    }

    function deleteUser(idx) {
        userAccounts.splice(idx, 1);
        populateUserAccounts();
    }

    navigator.geolocation.getCurrentPosition(function success(position) {
        geoLat = position.coords.latitude;
        geoLon = position.coords.longitude;
        $('#lat').prop('placeholder', geoLat);
        $('#lon').prop('placeholder', geoLon);
        console.log("Got location: " + geoLat + ", " + geoLon);
    }, function error(err) {
        $.getJSON("http://ipinfo.io", function(ipinfo){
            console.log("Found location ["+ipinfo.loc+"] by ipinfo.io");
            var latLong = ipinfo.loc.split(",");
            geoLat = latLong[0];
            geoLon = latLong[1];
            $('#lat').prop('placeholder', geoLat);
            $('#lon').prop('placeholder', geoLon);
        });
    });

    ipcRenderer.on('update-ready', function(evt, url) {
        $('#update-notice').show();
    });

    ipcRenderer.on('pythonLog', function(evt, data) {
        console.log(data.msg);
        handleServerStatus(data.msg);
    });

    ipcRenderer.on('appLog', function(evt, data) {
        console.log(data.msg);
    });

    function startUpdate() {
        ipcRenderer.send('installUpdate');
    }

    function verifyAndAddAccount() {
        var acttype = $('input[name=acttype]:checked', '#act_form').val();
        if (acttype == 'ptc') {
            doPTCLogin();
        } else {
            addAccount();
        }
    }

    function addAccount() {
        var acctInfo = {
            user: $('#username').val(),
            pass: $('#password').val(),
            type: $('input[name=acttype]:checked', '#act_form').val()
        };
        $('#username').val('');
        $('#password').val('');
        $('#add-acct').modal('hide');
        userAccounts.push(acctInfo);
        populateUserAccounts();
    }

    function doLogin(ssoUrl, callback) {
      var authWindow = new BrowserWindow(
        { width: 800, height: 600, show: false,
            'node-integration': false, title: 'Login' });

      authWindow.loadURL(ssoUrl);
      authWindow.show();

      authWindow.webContents.on('will-navigate', function (event, newUrl) {
        callback(authWindow, newUrl);
      });

      authWindow.webContents.on('did-navigate', function (event, newUrl) {
        callback(authWindow, newUrl);
      });

      authWindow.webContents.on('did-get-redirect-request', function (event, oldUrl, newUrl) {
        callback(authWindow, newUrl);
      });

      // Reset the authWindow on close
      authWindow.on('close', function() {
          authWindow = null;
          toggleLogin(false);
      }, false);
    }

    function toggleLogin(disabled) {
        saveState();
        jQuery('.login').prop("disabled", disabled);
    }

    function checkParams() {
        if ($('#maps_api_key').val() == '') {
            alert('Invalid Google Maps API key. Please follow instructions to set API key before login.');
            return false;
        }
        if ($('#radius').val() != '') {
            if (!$('#radius').val().match(/^[0-9]+$/)) {
                alert('Invalid Radius. Only numbers allowed.');
                return false;
            }
        }
        if (userAccounts.length <= 0) {
            alert('You must add at least 1 account.');
            return false;
        }
        return true;
    }

    function doPTCLogin() {
        toggleLogin(true);
        jQuery('#ptc_errors').html('');
        var username = jQuery('#username').val(),
            password = jQuery('#password').val();

        // Reset cookie jar
        ptcJar = request.jar();

        // Get Login session from SSO servers
        ptcReq.get('https://sso.pokemon.com/sso/login?service=https%3A%2F%2Fsso.pokemon.com%2Fsso%2Foauth2.0%2FcallbackAuthorize',
        function(error, response, body) {
            if (!error && response.statusCode == 200) {
                doPTCLoginStep2(username, password, JSON.parse(body));
            } else {
                console.log(error);
                toggleLogin(false);
                alert('Oops! Something went wrong and we couldn\'t ' +
                    'log you in. Please try again.\n' +
                    'Unable to get login session from Pokemon SSO.');
            }
        });

        return false;
    }

    function doPTCLoginStep2(user, pass, session) {
        var loginData = {
            'lt': session.lt,
            'execution': session.execution,
            '_eventId': 'submit',
            'username': user,
            'password': pass
        };

        ptcReq.post(
                'https://sso.pokemon.com/sso/login?service=https%3A%2F%2Fsso.pokemon.com%2Fsso%2Foauth2.0%2FcallbackAuthorize',
                {form: loginData},
                function (error, response, body) {
                    if (!error && response.statusCode == 302) {
                        var rawRedirect = response.headers.location;
                        handlePokemonCallback(rawRedirect);
                    } else {
                        toggleLogin(false);
                        var errors = null;
                        try {
                            errors = JSON.parse(body).errors;
                            errors = errors.join(' ');
                        } catch(e) {}
                        if (errors) {
                            jQuery('#ptc_errors').html(errors);
                        } else {
                            alert('Oops! Something went wrong and we couldn\'t ' +
                                  'log you in. Please try again.\n' +
                                  'Unable to finish login with Pokemon SSO.');
                        }
                    }
                }
            );
    }

    function handlePokemonCallback(newUrl) {
      toggleLogin(false);
      addAccount();
    }

    function startServer() {
        if (!checkParams()){
            return;
        }
        completeLogin('', '');
    }

    function completeLogin(auth, code) {
        var userLat = $('#lat').val(),
            userLon = $('#lon').val();
        if (userLat != '') {
            geoLat = userLat;
        }
        if (userLon != '') {
            geoLon = userLon;
        }
        ipcRenderer.send('startPython', auth, code, geoLat, geoLon, {
            is_public: checked('is_public'),
            //fast_scan: checked('fast_scan'),
            radius: $('#radius').val(),
            maps_api_key: $('#maps_api_key').val(),
            accounts: userAccounts
        });
    }

    function doGeolocate() {
        if($("#address").val().trim().length == 0) {
            return;
        }
        toggleGeolocate(true);
        $.ajax("https://maps.googleapis.com/maps/api/geocode/json?address=" + $("#address").val().replace(/ /gi,"+"))
            .done(doGeolocateCallback)
            .fail(function(xhr, status, err){
                alert("There was an error looking up this address, please try again");
                toggleGeolocate(true);
            });
    }

    function doGeolocateCallback(data) {
        toggleGeolocate(false);
        if(data.status != "OK" || data.results.length == 0) {
            alert("There was an error looking up this address, please try again");
            return;
        }

        var loc = data.results[0];
        console.log("Found location ["+loc.geometry.location.lat+","+loc.geometry.location.lng+"] by google geocode api");

        $("#lat").val(loc.geometry.location.lat);
        $("#lon").val(loc.geometry.location.lng);
    }

    function toggleGeolocate(disabled) {
        if(disabled == null) {
            disabled = $("#address").val().trim().length == 0;
        }
        jQuery('#address-locate').prop("disabled", disabled);
    }

  </script>

</html>
